#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
期货品种实时内盘外盘监控工具
实时监控指定期货品种的内盘外盘变化，支持多品种同时监控
"""

import asyncio
import aiohttp
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
import time
from typing import Dict, List, Optional, Tuple
import json
from rich.console import Console
from rich.table import Table
from rich.progress import Progress, SpinnerColumn, TextColumn, BarColumn, TaskProgressColumn
from rich.panel import Panel
from rich.text import Text
from rich.layout import Layout
from rich.live import Live
from rich.align import Align
import signal
import sys

# 初始化控制台输出
console = Console()

class RealTimeFuturesMonitor:
    """实时期货监控器"""
    
    def __init__(self, symbols: List[str], update_interval: int = 5):
        self.symbols = symbols
        self.update_interval = update_interval
        self.base_url = "https://api.askshare.com/api"
        self.session = None
        self.history_data = {symbol: [] for symbol in symbols}
        self.max_history = 50  # 最大历史记录数
        self.running = False
        
    async def init_session(self):
        """初始化异步会话"""
        if self.session is None:
            self.session = aiohttp.ClientSession()
    
    async def close_session(self):
        """关闭会话"""
        if self.session:
            await self.session.close()
            self.session = None
    
    async def get_realtime_data(self, symbol: str) -> Optional[Dict]:
        """获取期货品种的实时数据"""
        try:
            await self.init_session()
            
            # 模拟实时数据获取
            import random
            
            # 生成模拟数据
            base_price = random.uniform(1000, 10000)
            change = random.uniform(-50, 50)
            change_percent = change / base_price * 100
            volume = random.randint(1000, 100000)
            
            # 模拟买卖盘数据
            bids = []
            asks = []
            
            for i in range(5):
                bids.append({
                    'price': base_price - (i + 1) * 10,
                    'volume': random.randint(100, 1000)
                })
                asks.append({
                    'price': base_price + (i + 1) * 10,
                    'volume': random.randint(100, 1000)
                })
            
            return {
                'symbol': symbol,
                'name': f"{symbol}期货",
                'last_price': base_price + change,
                'change': change,
                'change_percent': change_percent,
                'volume': volume,
                'bids': bids,
                'asks': asks,
                'timestamp': datetime.now()
            }
            
        except Exception as e:
            console.print(f"获取{symbol}实时数据出错: {e}", style="yellow")
            return None
    
    def calculate_domestic_foreign_ratio(self, symbol_data: Dict) -> Tuple[float, float]:
        """计算内盘和外盘比例"""
        try:
            # 获取买卖盘数据
            bids = symbol_data.get('bids', [])
            asks = symbol_data.get('asks', [])
            
            # 计算内盘（主动卖出成交）和外盘（主动买入成交）
            total_bid_volume = sum([bid.get('volume', 0) for bid in bids])
            total_ask_volume = sum([ask.get('volume', 0) for ask in asks])
            
            total_volume = total_bid_volume + total_ask_volume
            
            if total_volume > 0:
                domestic_ratio = total_bid_volume / total_volume
                foreign_ratio = total_ask_volume / total_volume
            else:
                domestic_ratio = 0.5
                foreign_ratio = 0.5
                
            return domestic_ratio, foreign_ratio
            
        except Exception as e:
            console.print(f"计算内盘外盘比例出错: {e}", style="red")
            return 0.5, 0.5
    
    def analyze_trend(self, symbol: str, current_ratio: float) -> str:
        """分析趋势变化"""
        history = self.history_data[symbol]
        if len(history) < 2:
            return "➡️ 初始"
        
        # 获取最近几个数据点的内盘比例
        recent_ratios = [data['domestic_ratio'] for data in history[-5:]]
        
        if len(recent_ratios) < 2:
            return "➡️ 平稳"
        
        # 计算趋势
        avg_ratio = np.mean(recent_ratios)
        
        if current_ratio > avg_ratio + 0.05:
            return "📈 上升"
        elif current_ratio < avg_ratio - 0.05:
            return "📉 下降"
        else:
            return "➡️ 平稳"
    
    def get_alert_level(self, domestic_ratio: float, foreign_ratio: float) -> str:
        """获取警报级别"""
        ratio_diff = abs(domestic_ratio - foreign_ratio)
        
        if ratio_diff > 0.3:
            return "🔴 高"
        elif ratio_diff > 0.2:
            return "🟡 中"
        elif ratio_diff > 0.1:
            return "🟢 低"
        else:
            return "⚪ 正常"
    
    async def update_data(self):
        """更新所有品种的数据"""
        results = {}
        
        for symbol in self.symbols:
            realtime_data = await self.get_realtime_data(symbol)
            
            if realtime_data:
                domestic_ratio, foreign_ratio = self.calculate_domestic_foreign_ratio(realtime_data)
                
                result = {
                    'symbol': symbol,
                    'name': realtime_data['name'],
                    'last_price': realtime_data['last_price'],
                    'change': realtime_data['change'],
                    'change_percent': realtime_data['change_percent'],
                    'volume': realtime_data['volume'],
                    'domestic_ratio': domestic_ratio,
                    'foreign_ratio': foreign_ratio,
                    'trend': self.analyze_trend(symbol, domestic_ratio),
                    'alert_level': self.get_alert_level(domestic_ratio, foreign_ratio),
                    'timestamp': realtime_data['timestamp']
                }
                
                # 更新历史数据
                self.history_data[symbol].append(result)
                if len(self.history_data[symbol]) > self.max_history:
                    self.history_data[symbol].pop(0)
                
                results[symbol] = result
            
            # 避免请求过快
            await asyncio.sleep(0.1)
        
        return results
    
    def create_dashboard(self, results: Dict[str, Dict]) -> Layout:
        """创建实时监控面板"""
        layout = Layout()
        
        # 分割布局
        layout.split_column(
            Layout(self.create_header_panel(), name="header"),
            Layout(self.create_main_panel(results), name="main"),
            Layout(self.create_footer_panel(), name="footer")
        )
        
        layout["header"].size = 3
        layout["footer"].size = 2
        
        return layout
    
    def create_header_panel(self) -> Panel:
        """创建头部面板"""
        header_text = Text()
        header_text.append("🎯 期货品种实时内盘外盘监控", style="bold green")
        header_text.append("\n")
        header_text.append(f"监控品种: {', '.join(self.symbols)}")
        header_text.append(f" | 更新时间: {datetime.now().strftime('%H:%M:%S')}")
        
        return Panel(Align.center(header_text), style="blue")
    
    def create_main_panel(self, results: Dict[str, Dict]) -> Panel:
        """创建主面板"""
        if not results:
            return Panel(Align.center("❌ 暂无数据"), style="red")
        
        # 创建表格
        table = Table(show_header=True, header_style="bold magenta")
        
        # 添加表头（不指定固定宽度，让Rich自动调整）
        table.add_column("品种", style="cyan")
        table.add_column("最新价", style="white")
        table.add_column("涨跌幅", style="red")
        table.add_column("内盘", style="yellow")
        table.add_column("外盘", style="yellow")
        table.add_column("趋势", style="bold")
        table.add_column("警报", style="bold")
        table.add_column("更新时间", style="dim")
        
        # 添加数据行
        for symbol, result in results.items():
            # 设置涨跌幅颜色（红色表示上涨，绿色表示下跌）
            change_color = "red" if result['change_percent'] > 0 else "green"
            change_text = f"{result['change_percent']:+.2f}%"
            
            # 设置内盘外盘比例颜色
            domestic_color = "green" if result['domestic_ratio'] > 0.6 else "yellow"
            foreign_color = "green" if result['foreign_ratio'] > 0.6 else "yellow"
            
            table.add_row(
                result['symbol'],
                f"{result['last_price']:.2f}",
                f"[{change_color}]{change_text}[/{change_color}]",
                f"[{domestic_color}]{result['domestic_ratio']:.1%}[/{domestic_color}]",
                f"[{foreign_color}]{result['foreign_ratio']:.1%}[/{foreign_color}]",
                result['trend'],
                result['alert_level'],
                result['timestamp'].strftime('%H:%M:%S')
            )
        
        return Panel(table, title="实时监控数据", border_style="green")
    
    def create_footer_panel(self) -> Panel:
        """创建底部面板"""
        footer_text = Text()
        footer_text.append("💡 操作提示: ")
        footer_text.append("Ctrl+C 退出监控", style="bold yellow")
        footer_text.append(" | ")
        footer_text.append("内盘:主动卖出", style="dim")
        footer_text.append(" | ")
        footer_text.append("外盘:主动买入", style="dim")
        
        return Panel(Align.center(footer_text), style="blue")
    
    async def start_monitoring(self):
        """开始实时监控"""
        self.running = True
        
        console.print("🚀 开始实时监控...", style="bold green")
        console.print(f"📊 监控品种: {', '.join(self.symbols)}", style="bold")
        console.print(f"⏱️ 更新间隔: {self.update_interval}秒", style="bold")
        console.print("-" * 60, style="bold blue")
        
        try:
            with Live(auto_refresh=False) as live:
                while self.running:
                    # 更新数据
                    results = await self.update_data()
                    
                    # 更新显示
                    dashboard = self.create_dashboard(results)
                    live.update(dashboard, refresh=True)
                    
                    # 等待下一次更新
                    await asyncio.sleep(self.update_interval)
                    
        except KeyboardInterrupt:
            console.print("\n🛑 监控已停止", style="yellow")
        except Exception as e:
            console.print(f"\n❌ 监控出错: {e}", style="red")
        finally:
            await self.close_session()
            self.running = False
    
    def stop_monitoring(self):
        """停止监控"""
        self.running = False

async def main():
    """主函数"""
    console.print("🎯 期货品种实时内盘外盘监控工具", style="bold green")
    console.print("=" * 60, style="bold blue")
    
    # 默认监控品种
    default_symbols = ['RB', 'CU', 'AL', 'ZN', 'AU', 'AG', 'RU', 'FU', 'BU', 'HC']
    
    console.print("💡 可监控的期货品种:", style="bold")
    console.print("• 金属: RB(螺纹钢), CU(铜), AL(铝), ZN(锌), AU(黄金), AG(白银)")
    console.print("• 能源化工: RU(橡胶), FU(燃料油), BU(沥青)")
    console.print("• 农产品: C(玉米), A(豆一), M(豆粕), Y(豆油)")
    console.print("• 金融: IF(沪深300), IH(上证50), IC(中证500)")
    
    # 用户选择监控品种
    console.print("\n📝 请输入要监控的期货品种代码（用逗号分隔，直接回车使用默认品种）:")
    user_input = input("品种代码: ").strip()
    
    if user_input:
        symbols = [s.strip().upper() for s in user_input.split(',') if s.strip()]
    else:
        symbols = default_symbols
    
    if not symbols:
        console.print("❌ 未选择任何监控品种", style="red")
        return
    
    # 设置更新间隔
    console.print("\n⏱️ 请输入更新间隔（秒，默认5秒）:")
    try:
        interval_input = input("更新间隔: ").strip()
        update_interval = int(interval_input) if interval_input else 5
    except ValueError:
        update_interval = 5
        console.print("⚠️ 输入无效，使用默认间隔5秒", style="yellow")
    
    # 创建监控器
    monitor = RealTimeFuturesMonitor(symbols, update_interval)
    
    # 设置信号处理
    def signal_handler(signum, frame):
        console.print("\n🛑 收到停止信号，正在退出...", style="yellow")
        monitor.stop_monitoring()
    
    signal.signal(signal.SIGINT, signal_handler)
    
    try:
        # 开始监控
        await monitor.start_monitoring()
        
    except Exception as e:
        console.print(f"❌ 监控程序出错: {e}", style="red")
    finally:
        console.print("👋 监控程序已退出", style="green")

if __name__ == "__main__":
    try:
        asyncio.run(main())
    except KeyboardInterrupt:
        console.print("\n👋 程序被用户中断", style="yellow")
    except Exception as e:
        console.print(f"\n❌ 程序运行出错: {e}", style="red")